
package com.example.devecohp;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;

/**
 * The entry point for batch audit that allow the user to audit all files in a folder
 */
public class AuditAllFiles extends AnAction {
    /**
     * The entry point for audit all files
     * @param anActionEvent an AnActionEvent containing information about the action
     */
    @Override
    public void actionPerformed(@NotNull AnActionEvent anActionEvent) {

        VirtualFile virtualFile=anActionEvent.getData(CommonDataKeys.VIRTUAL_FILE);
        if(virtualFile==null){
            return;
        }
        PsiDirectory directory = PsiManager.getInstance(anActionEvent.getProject()).findDirectory(virtualFile);
        List<PsiFile> allFiles;
        if(directory==null){
            allFiles = new ArrayList<>();
            PsiFile file = PsiManager.getInstance(anActionEvent.getProject()).findFile(virtualFile);
            if(file!=null){
                allFiles.add(file);
            }else {
                return;
            }
        }else {
            allFiles = getAllFiles(directory);
        }
        auditAllFiles(allFiles,anActionEvent.getProject(),"");

    }
    public static void auditAllFiles(List<PsiFile> allFiles, Project project, String auditorPath){

        //List<String> filenames = new ArrayList<>();


        Application app = ApplicationManager.getApplication();
        ToolWindowInfo toolWindowInfo = PageManager.getInstance(project).getToolWindowInfo();
        toolWindowInfo.clear();
        PageManager.getInstance(project).setModeKeep();

        final int[] count = {0};
        //for(PsiFile f:allFiles){

        Auditor.runAndCreatePageInfo(project, allFiles, new Auditor.createPageInfoCallback() {
            @Override
            public void run(PageInfo pageInfo) {
                app.invokeLater(() -> {
                    DumbService.getInstance(project).runWhenSmart(() -> {
                        count[0] = count[0] + 1;
                        if (pageInfo != null) {
                            toolWindowInfo.addNodeForPage(pageInfo);
                            toolWindowInfo.reloadTree();
                        }
                        if (count[0] >= allFiles.size()) {
                            toolWindowInfo.expandAll();
                            MyToolWindowFactory.updateUpperPanel(project);
                            PageManager.getInstance(project).filterAllRules(toolWindowInfo.filterTextField.getText());
                        }


                    });
                });
            }

            @Override
            public void onCancle() {
                count[0]=allFiles.size();
            }
        }, false,auditorPath);

        //}

    }

    /**
     *
     * @param dir a PsiDirectory serve as the root of the search
     * @return all file in dir that end with .ts, .ets and .js
     */
    public static List<PsiFile> getAllFiles(PsiDirectory dir){
        List<PsiFile> result = new ArrayList<>();
        for(PsiElement element:dir.getChildren()){
            if(element instanceof PsiDirectory){
                result.addAll(getAllFiles((PsiDirectory)element));
            }else if(element instanceof PsiFile){
                if(((PsiFile)element).getName().endsWith(".ts")||((PsiFile)element).getName().endsWith(".ets")||((PsiFile)element).getName().endsWith(".js")){
                    if(!ConfigHelper.isConfigFile((PsiFile) element)) {
                        result.add((PsiFile) element);
                    }
                }
            }
        }
        return result;
    }
}
